package com.gengzp.rpc.proxy;

import com.gengzp.rpc.annotations.RpcReference;
import com.gengzp.rpc.annotations.RpcService;
import com.gengzp.rpc.core.RemoteTransactionalCoreFunc;
import com.gengzp.rpc.core.RpcCoreFunc;
import com.gengzp.rpc.factory.RpcBeanFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Proxy;

/**
 * @ClassName RpcProxyFactory
 * @Description 远程调用框架代理工厂
 * @Author gengzp
 * @Date 2025/5/31 23:33
 */
@Component
public class RpcProxyProcessor implements BeanPostProcessor {

    @Autowired
    private RpcCoreFunc rpcCoreFunc;

    @Autowired
    private RpcBeanFactory rpcBeanFactory;

    @Autowired
    private RemoteTransactionalCoreFunc remoteTransactionalCoreFunc;

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // 拿到 bean 的 .class 文件
        Class<?> targetClass = bean.getClass();
        // 取出类中的字段
        Field[] declaredFields = targetClass.getDeclaredFields();

        for (Field field : declaredFields) {
            if (!field.isAnnotationPresent(RpcReference.class)) {
                continue;
            }

            // 若字段带有 @RpcReference 注解, 表示远程调用接口
            Class<?> rpcInterfaceClass = field.getType();
            // 取出远程调用接口上, @RpcService 注解中指定的远程服务名称
            String remoteServiceName;
            try {
                remoteServiceName = rpcInterfaceClass.getAnnotation(RpcService.class).serviceName();
            } catch (Exception e) {
                throw new RuntimeException(rpcInterfaceClass.getTypeName() + " 远程服务名称未指定, 请检查接口是否正确定义 @RpcService 注解", e);
            }
            // 创建代理对象
            Object proxyInstance = Proxy.newProxyInstance(targetClass.getClassLoader(),
                    new Class[]{rpcInterfaceClass},
                    new RpcInvocationHandler(remoteServiceName,
                            rpcCoreFunc,
                            rpcBeanFactory.getRpcHttpRequestInterceptor(),
                            remoteTransactionalCoreFunc,
                            rpcBeanFactory.getRemoteTransactionHandler()));
            // 设置代理实例
            field.setAccessible(true);
            try {
                field.set(bean, proxyInstance);
            } catch (IllegalAccessException e) {
                throw new RuntimeException("设置代理实例失败", e);
            }
        }
        return bean;
    }

}
